import { injectable, inject } from 'inversify';
import { DataSource, Repository } from 'typeorm';
import { User } from '../../../domain/entities/user.entity';
import { IUserRepository } from './interfaces/IRepository';
import { TYPES } from '../../ioc/types';
import { LoggerService } from '../../logging/logger.service';

@injectable()
export class UserRepository implements IUserRepository<User> {
  private repository: Repository<User>;

  constructor(
    @inject(TYPES.DataSource) dataSource: DataSource,
    @inject(TYPES.LoggerService) private logger: LoggerService
  ) {
    this.repository = dataSource.getRepository(User);
  }

  async save(user: User): Promise<User> {
    try {
      return await this.repository.save(user);
    } catch (error: any) {
      this.logger.error(`Error saving user: ${error.message}`);
      throw error;
    }
  }

  async findById(id: string): Promise<User | null> {
    try {
      return await this.repository.findOneBy({ id });
    } catch (error: any) {
      this.logger.error(`Error finding user by ID: ${error.message}`);
      return null;
    }
  }

  async findOne(options: any): Promise<User | null> {
    try {
      return await this.repository.findOne(options);
    } catch (error: any) {
      this.logger.error(`Error finding user: ${error.message}`);
      return null;
    }
  }

  async find(options?: any): Promise<User[]> {
    try {
      return await this.repository.find(options || {});
    } catch (error: any) {
      this.logger.error(`Error finding users: ${error.message}`);
      return [];
    }
  }

  async delete(id: string): Promise<void> {
    try {
      await this.repository.delete(id);
    } catch (error: any) {
      this.logger.error(`Error deleting user: ${error.message}`);
      throw error;
    }
  }

  async findByUsername(username: string): Promise<User | null> {
    try {
      return await this.repository.findOneBy({ username });
    } catch (error: any) {
      this.logger.error(`Error finding user by username: ${error.message}`);
      return null;
    }
  }

  async findByEmail(email: string): Promise<User | null> {
    try {
      return await this.repository.findOneBy({ email });
    } catch (error: any) {
      this.logger.error(`Error finding user by email: ${error.message}`);
      return null;
    }
  }
}